package edu.washington.ling.syntric.proc;

import org.apache.commons.configuration.*;
import org.apache.commons.lang.StringUtils;

import edu.washington.ling.syntric.io.TreeFileReader;
import edu.washington.ling.syntric.io.TreeFileWriter;
import edu.washington.ling.syntric.io.TreeReader;
import edu.washington.ling.syntric.io.TreeRepresentation;
import edu.washington.ling.syntric.io.TreeWriter;
import edu.washington.ling.syntric.struct.error.ExceptionHandler;
import edu.washington.ling.syntric.struct.error.PrintingExceptionHandler;
import edu.washington.ling.syntric.struct.error.UnreadableRepresentationException;
import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.struct.tree.Tree;

import java.util.List;
import java.util.LinkedList;
import java.util.NoSuchElementException;



public class ExtractSentences {

	private static ExceptionHandler pHandler = new PrintingExceptionHandler();
	
	private static String inputFilePath;
	private static String inputTreeFormat;
	private static String inputTreeType;
	private static String inputFileFormat;
	private static String outputFilePath;
	private static String outputTreeFormat;
	private static String outputTreeType;
	private static String outputFileFormat;
	
	private static String extractSentence(Tree t) {
		List<String> words = new LinkedList<String>();
		for (Token tok: t.getTokenList()) {
			if (!tok.isEmptyCategory())
				words.add(tok.getWord());
		}
		return StringUtils.join(words, " ");
	}

	private static void extractSentencesFromInput() {
		int numExtracted = 0;
		int numTrees = 0;
		
		try {
			TreeFileReader tfr = TreeFileReader.newReader(inputFilePath, inputFileFormat);
			TreeFileWriter tfw = TreeFileWriter.newWriter(outputFilePath, outputFileFormat);
			TreeReader tr = TreeReader.newReader(inputTreeType, inputTreeFormat);
			TreeWriter tw = TreeWriter.newWriter(outputTreeType, outputTreeFormat);
			TreeRepresentation trep = null;
			while ((trep = tfr.readNextTreeRep()) != null) {
				try {
					Tree t = tr.readTree(trep);
					trep = tw.writeTree(t);
					trep.setOriginal(extractSentence(t));
					tfw.writeTreeRep(trep);
					numExtracted++;
				}
				catch (UnreadableRepresentationException e) {
					pHandler.handle(e, "could not process representation.");
				}
				finally {
					numTrees++;
				}
			}
			tfw.close();
		}
		catch (Exception e) {
			pHandler.handle(e, "Sentence extraction failed.");
			e.printStackTrace();
			System.exit(1);
		}
		System.out.println("Sentence extraction was successful.");
		System.out.println(String.format("%d/%d sentences were successfully extracted.", numExtracted, numTrees));
	}
	public static void main(String[] args) {
		if (args.length != 1) {
			System.err.println("Error: incorrect number of arguments.");
			System.err.println("Usage: ExtractSentences config.xml");
			System.exit(1);
		}
		try {
			XMLConfiguration config = new XMLConfiguration(args[0]);
			config.setThrowExceptionOnMissing(true);
			inputFilePath = config.getString("proc-001.files.input.path");
			inputFileFormat = config.getString("proc-001.files.input.fileformat");
			inputTreeFormat = config.getString("proc-001.files.input.treeformat");
			inputTreeType = config.getString("proc-001.files.input.treetype");
			outputFilePath = config.getString("proc-001.files.output.path");
			outputFileFormat = config.getString("proc-001.files.output.fileformat");
			outputTreeFormat = config.getString("proc-001.files.output.treeformat");
			outputTreeType = config.getString("proc-001.files.output.treetype");
		}
		catch(ConfigurationException e) {
			String errStr = String.format("configuration file \'%s\' could not be read.", args[0]);
			pHandler.handle(e, errStr);
			System.exit(1);
		}
		catch(NoSuchElementException e) {
			String errStr = String.format("configuration file \'%s\' is incomplete.", args[0]);
			pHandler.handle(e, errStr);
			System.exit(1);
		}
		extractSentencesFromInput();
	}
}
